package com.gitee.wsl.mathematics.geometry.d2.curve

import com.gitee.wsl.mathematics.vector.ext.cross
import com.gitee.wsl.mathematics.vector.vec2.Vec2f

internal fun signum(d: Double): Double {
    return if (d == 0.0 || d.isNaN()) d else if (d < 0) -1.0 else 1.0
}

object Bezier2 {
    
    fun curve(p0: Vec2f, p1: Vec2f) = CurveLine.line(p0, p1)
    fun curve(p0: Vec2f, p1: Vec2f, p2: Vec2f) = QuadraticBezier2(p0, p1, p2)

    fun curve(
        p0: Vec2f,
        p1: Vec2f,
        p2: Vec2f,
        p3: Vec2f
    ): CurveShape2d {
        return CubicBezier2(p0, p1, p2, p3)
    }

    fun sign(n: Float) = sign(n.toDouble()).toFloat()

    fun sign(n: Double): Double {
        val s = signum(n)
        return if (s == 0.0) -1.0 else s
    }

    fun <V : CurveShape2d> subdivide(
        result: MutableList<Vec2f>,
        c: V,
        error: (V) -> Float,
        maxError: Double
    ) {
        if (error(c) <= maxError) {
            result.add(c.start())
        } else {
            val split: Array<CurveShape2d> = c.split(0.5)
            @Suppress("UNCHECKED_CAST")
            subdivide(result, split[0] as V, error, maxError)
            @Suppress("UNCHECKED_CAST")
            subdivide(result, split[1] as V, error, maxError)
        }
    }

    fun signedDistance(p: Vec2f, a: Vec2f, b: Vec2f): Float {
        val d: Vec2f = b - a
        return ((p cross  d) + (b cross  a)) / d.length
    }

}
